home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows 95 API Bible
/
Windows 95 API Bible 3 Disc Set.iso
/
Win32 API Bible Book 3 of 3
/
CHAPTE10
/
BLINDTRS
/
LINE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-28
|
25KB
|
759 lines
#include <windows.h>
#include <windowsx.h>
#include "line.h"
#include "tapi.h"
#define BUFSIZE 256
#define APIHIVERSION 0x00010028 /* 1.40 */
#define APILOWVERSION 0x00010000 /* 1.0 */
#define EXTHIVERSION 0x00010005 /* 1.5 */
#define EXTLOWVERSION 0x00000009 /* 0.9 */
#define OWNER 0
#define MONITOR 1
#define MAX_CALL 3
#define MAX_LINE 2
#if defined (WIN32)
#define IS_WIN32 TRUE
#else
#define IS_WIN32 FALSE
#endif
#define IS_NT IS_WIN32 && (BOOL)(GetVersion() < 0x80000000)
#define IS_WIN32S IS_WIN32 && (BOOL)(!(IS_NT) && (LOBYTE(LOWORD(GetVersion()))<4))
#define IS_WIN95 (BOOL)(!(IS_NT) && !(IS_WIN32S)) && IS_WIN32
LPCTSTR lpszAppName = "lineBlindTransfer";
LPCTSTR lpszTitle = "lineBlindTransfer";
HINSTANCE hInst; // current instance
HWND hWnd; // parent window handle
HWND hListWnd; // listbox
HDC hdc;
TEXTMETRIC tm ;
BOOL RegisterWin95( CONST WNDCLASS* lpwc );
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (hInstance, lpszAppName);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
if ( IS_WIN95 )
{
if ( !RegisterWin95( &wc ) )
return( FALSE );
}
else if ( !RegisterClass( &wc ) )
return( FALSE );
hInst = hInstance;
hWnd = CreateWindow( lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);
if ( !hWnd )
return( FALSE );
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
while( GetMessage( &msg, NULL, 0, 0) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return( msg.wParam );
}
BOOL RegisterWin95( CONST WNDCLASS* lpwc )
{
WNDCLASSEX wcex;
wcex.style = lpwc->style;
wcex.lpfnWndProc = lpwc->lpfnWndProc;
wcex.cbClsExtra = lpwc->cbClsExtra;
wcex.cbWndExtra = lpwc->cbWndExtra;
wcex.hInstance = lpwc->hInstance;
wcex.hIcon = lpwc->hIcon;
wcex.hCursor = lpwc->hCursor;
wcex.hbrBackground = lpwc->hbrBackground;
wcex.lpszMenuName = lpwc->lpszMenuName;
wcex.lpszClassName = lpwc->lpszClassName;
// Added elements for Windows 95.
//...............................
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.hIconSm = LoadImage(wcex.hInstance, lpwc->lpszClassName,
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR );
return RegisterClassEx( &wcex );
}
#define CONFCALL 1
#define CONSULT 2
enum CallState
{
Idle,
Offering,
Accepted,
Dialtone,
Dialing,
Ringback,
Busy,
Special,
Connected,
Proceeding,
Conferenced,
Onholdconf,
Disconnected,
Unknown
};
typedef struct tagMYINFO // general application information
{
HLINEAPP lineApp; // instance handle TAPI gives back to us through lineInitialize()
DWORD dwNumDevices; // number of available devices
DWORD dwAPIVersion; // API version the line supports
DWORD dwExtVersion; // extended version
char szLocation[128]; // location
char szCallingCard[128]; // calling card being used
char szAreaCode[4]; // area code
char szCountry[128]; // calling card being used
} MYINFO;
typedef struct tagLINEINFO // information on an open line
{
DWORD dwNumAddress; // number of available addresses on the line
HLINE hLine; // handle to the line as returned by lineOpen
DWORD dwLineID; // the line ID of this line
char szLineName[128]; // the line's name
} MYLINEINFO;
typedef struct tagMYCALLINFO //information on a call
{
DWORD eCallState; // TAPI's line call State, set as user-defined enums
DWORD dwRequestID; // requestID returned by async TAPI functions lineMakeCall/lineDropCall
DWORD dwAddressID; // the originating address ID of the call being made
LPCSTR lpszAddress;
HLINE hLine; // handle to the line
HCALL hCall; // handle to the call
char szDialString[TAPIMAXDESTADDRESSSIZE]; //phone number being dialed
char szDialStringOriginal[TAPIMAXDESTADDRESSSIZE];
char szDialStringCanonical[TAPIMAXDESTADDRESSSIZE];
char szCalledParty[TAPIMAXCALLEDPARTYSIZE]; // name of the party
DWORD dwTranslateResults;
} MYCALLINFO;
enum CallAction // Declare enum type CallAction (used in lineSetAppSpecific)
{
HOLD, // hold the call
TRANSFER, // transfer the call
REDIRECT, // redirect the call
DROP, // drop the call
PARK // park the call
};
MYINFO myInfo; //instance of MYINFO structure
MYLINEINFO myLineInfo[MAX_LINE]; //instance of MYLINEINFO structure
MYCALLINFO myCallInfo[MAX_CALL]; //array of MYCALLINFO strcuture
LONG lRet; //return code
char buf[BUFSIZE]; // buffer for debug message
DWORD dwLineID = 0;
DWORD i;
LINEEXTENSIONID ext_id;
LINEDEVCAPS *plineDevCaps;
LINEADDRESSCAPS *plineAdddressCaps;
LINEADDRESSSTATUS *plineAddressStat;
LINECALLINFO *plineCallInfo;
LINECALLSTATUS *plineCallStatus;
LINECALLLIST *plineCallList;
LINEDEVSTATUS *plineDevStatus;
LINETRANSLATECAPS *plineTranslateCaps;
LINETRANSLATEOUTPUT *plineTranslateOutput;
LINECALLPARAMS *plineCallParams;
LINEDEVSTATUS *plineDevStatus;
LINEFORWARDLIST *plineForwardList;
LINETRANSLATECAPS *plineTranslateCaps;
LINEREQMAKECALL lineReqMakeCall;
VARSTRING *pDeviceConfig;
VARSTRING *pDeviceId;
VARSTRING *pNonDirAddress;
LPLINELOCATIONENTRY lineLocEntry;
LPLINECARDENTRY lineCardEntry;
LINECOUNTRYLIST *plineCountryList;
LPLINECOUNTRYENTRY lineCE;
LPSTR lpData;
HICON hIcon = NULL; //used in lineGetID();
DWORD dwNumRings; //used in lineGetNumRings();
HCALL hConsultCall; //handle to consultation linePrepareAddToConference, SetupConference
HCALL hConfCall; //handle to consultation linePrepareAddToConference, SetupConference
HCALL hParkedCall;
DWORD dwCompletionID; //used in lineCompleteCall()
char szName[128];
char szNumber[128];
char szDigits[128];
char szDevConfig[128];
LONG lRet;
char buf[BUFSIZE];
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_COMMAND :
switch( LOWORD( wParam ) )
{
case IDM_RUN :
DialogBox( hInst, "IDD_DIALNUM", hWnd, (DLGPROC)Dial );
break;
case IDM_ABOUT :
{
DialogBox( hInst, "AboutBox", hWnd, (DLGPROC)About );
break;
}
case IDM_EXIT :
{
for (i = 0; i < myInfo.dwNumDevices; i++)
lineClose(myLineInfo[i].hLine);
lineShutdown(myInfo.lineApp);
DestroyWindow( hWnd );
break;
}
}
break;
case WM_CREATE :
{
hdc = GetDC (hWnd) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hWnd, hdc) ;
hListWnd = CreateWindowEx( 0, "listbox",
" ",
WS_CHILD | WS_VISIBLE,
tm.tmAveCharWidth, tm.tmHeight * 3,
tm.tmAveCharWidth * 16 +
GetSystemMetrics (SM_CXVSCROLL),
tm.tmHeight * 5,
hWnd,
NULL,
hInst,
NULL
);
//lineInitialize
//...............................................
lRet = lineInitialize(&myInfo.lineApp, hInst, lineCallback, NULL, &myInfo.dwNumDevices);
if (lRet == 0)
{
wsprintf (buf, "lineInitialize suceeded!");
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
}
else
{
wsprintf ( buf,"lineInitialize failed, err=x%lx",lRet);
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
lineError(lRet);
break;
}
//lineNegotiateAPIVersion
//...............................................
lRet = lineNegotiateAPIVersion(myInfo.lineApp, 0, APILOWVERSION, APIHIVERSION,
&myInfo.dwAPIVersion, &ext_id);
if (lRet == 0)
{
wsprintf (buf, "lineNegotiateAPIVersion suceeded!");
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
}
else
{
wsprintf (buf, "lineNegotiateAPIVersion failed, err=x%lx",
lRet);
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
lineError(lRet);
lineShutdown (myInfo.lineApp);
break;
}
//lineNegotiateExtVersion
//...............................................
lRet = lineNegotiateExtVersion(myInfo.lineApp, 0, myInfo.dwAPIVersion, EXTLOWVERSION,
EXTHIVERSION, &myInfo.dwExtVersion);
if (lRet == 0)
{
wsprintf (buf, "lineNegotiateExtVersion suceeded!");
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
}
else
{
wsprintf (buf, "lineNegotiateExtVersion failed, err=x%lx",
lRet);
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
lineError(lRet);
}
//lineGetDevCaps
//for each line device, get capabilities until we find one that supports
//interactive voice
//...............................................
plineDevCaps = (LINEDEVCAPS *) calloc (1, sizeof(LINEDEVCAPS)+1000);
plineDevCaps->dwTotalSize = sizeof(LINEDEVCAPS) + 1000;
for (i = 0; i < myInfo.dwNumDevices; i++)
{
lineGetDevCaps(myInfo.lineApp, i, myInfo.dwAPIVersion, 0, plineDevCaps);
if (plineDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE)
{
myLineInfo[i].dwNumAddress = plineDevCaps->dwNumAddresses;
myLineInfo[i].dwLineID = i;
if (plineDevCaps->dwLineNameSize > 0)
strcpy(myLineInfo[i].szLineName,((LPSTR)(plineDevCaps)+plineDevCaps->dwLineNameOffset));
}
}
//lineOpen
//................................................................
lRet = lineOpen(myInfo.lineApp,myLineInfo[OWNER].dwLineID,&myLineInfo[OWNER].hLine,
myInfo.dwAPIVersion,0,(DWORD)lineCallback, LINECALLPRIVILEGE_NONE,
LINEMEDIAMODE_DATAMODEM, NULL);
if (lRet == 0)
{
wsprintf (buf, "lineOpen suceeded!");
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ; }
else
{
wsprintf ( buf,"lineOpen failed, err=x%lx", lRet);
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
lineError(lRet);
}
break;
}
case WM_SIZE:
MoveWindow(hListWnd,0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_DESTROY :
PostQuitMessage(0);
break;
default :
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) );
}
return( 0L );
}
/****************************************************************************
FUNCTION: lineCallback
PURPOSE: callback function handles line events
****************************************************************************/
LRESULT CALLBACK lineCallback (DWORD dwDevice, DWORD dwMsg,
DWORD dwCallbackInst, DWORD dwParam1,
DWORD dwParam2,DWORD dwParam3)
{
switch (dwMsg)
{
case LINE_CALLSTATE:
{
for (i = 0; i < MAX_CALL; i++)
{
if (dwDevice = (DWORD) myCallInfo[i].hCall)
switch (dwParam1)
{
case LINECALLSTATE_IDLE:
myCallInfo[i].eCallState = Idle;
break;
case LINECALLSTATE_OFFERING:
myCallInfo[i].eCallState = Offering;
break;
case LINECALLSTATE_ACCEPTED:
myCallInfo[i].eCallState = Accepted;
break;
case LINECALLSTATE_DIALTONE:
myCallInfo[i].eCallState = Dialtone;
break;
case LINECALLSTATE_DIALING:
myCallInfo[i].eCallState = Dialing;
break;
case LINECALLSTATE_RINGBACK:
myCallInfo[i].eCallState = Ringback;
break;
case LINECALLSTATE_BUSY:
myCallInfo[i].eCallState = Busy;
break;
case LINECALLSTATE_SPECIALINFO:
myCallInfo[i].eCallState = Special;
break;
case LINECALLSTATE_CONNECTED:
myCallInfo[i].eCallState = Connected;
//call lineBlindTransfer
//...............................
strcpy(myCallInfo[0].szDialString, "T5012100"); //from user
lRet = lineBlindTransfer(myCallInfo[0].hCall,
myCallInfo[0].szDialString, 0);
if (lRet > 0)
{
wsprintf (buf,"lineBlindTransfer succeeded!");
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
}
else
{
wsprintf (buf,"lineBlindTransfer failed,err=x%lx", lRet);
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
lineError(lRet);
}
break;
case LINECALLSTATE_PROCEEDING:
myCallInfo[i].eCallState = Proceeding;
break;
case LINECALLSTATE_CONFERENCED:
myCallInfo[i].eCallState = Conferenced;
break;
case LINECALLSTATE_ONHOLDPENDCONF:
break;
case LINECALLSTATE_DISCONNECTED:
myCallInfo[i].eCallState = Disconnected;
break;
case LINECALLSTATE_UNKNOWN:
myCallInfo[i].eCallState = Unknown;
break;
}
}
}
case LINE_MONITORMEDIA:
break;
case LINE_MONITORDIGITS:
break;
case LINE_MONITORTONE:
break;
//error handling for functions completed asynchronously
//.....................................................
case LINE_REPLY:
{
for (i = 0; i < MAX_CALL; i++)
{
if (dwParam1 = myCallInfo[i].dwRequestID)
{
if (dwParam2 != 0)
{
lineError((LONG) dwParam2);
break;
}
}
}
break;
}
case LINE_GENERATE:
break;
case LINE_REQUEST:
break;
case LINE_GATHERDIGITS:
break;
}
return (TRUE);
}
/****************************************************************************
FUNCTION: lineError
PURPOSE: line error messages
****************************************************************************/
void lineError (LONG lrc)
{
switch (lrc) {
case LINEERR_INVALAPPHANDLE:
MessageBox (hWnd, "Invalid app handle.", "", MB_OK);
break;
case LINEERR_BADDEVICEID:
MessageBox (hWnd,"The specified line device ID is out of range.", "",
MB_OK);
break;
case LINEERR_INCOMPATIBLEAPIVERSION:
MessageBox (hWnd, "Incompatible API version.", "", MB_OK);
break;
case LINEERR_ADDRESSBLOCKED:
MessageBox (hWnd, "Address was blocked.", "", MB_OK);
break;
case LINEERR_BEARERMODEUNAVAIL:
MessageBox (hWnd, "Bearer Mode Unavailable.", "", MB_OK);
break;
case LINEERR_CALLUNAVAIL:
MessageBox (hWnd, "Call appearances in use..", "", MB_OK);
break;
case LINEERR_INUSE:
MessageBox (hWnd, "Line in Use.", "", MB_OK);
break;
case LINEERR_INVALADDRESS:
MessageBox (hWnd, "Invalid Address.", "", MB_OK);
break;
case LINEERR_INVALADDRESSID:
MessageBox (hWnd, "Invalid Address ID.", "", MB_OK);
break;
case LINEERR_INVALCALLPARAMS:
MessageBox (hWnd, "Invalid Address ID.", "", MB_OK);
break;
case LINEERR_INCOMPATIBLEEXTVERSION:
MessageBox (hWnd, "Incompatible extension version.","", MB_OK);
break;
case LINEERR_NOMEM:
MessageBox (hWnd, "No memory","", MB_OK);
break;
case LINEERR_NODRIVER:
MessageBox (hWnd, "No driver loaded", "", MB_OK);
break;
case LINEERR_RESOURCEUNAVAIL:
MessageBox (hWnd, "Resource overcommittment", "", MB_OK);
break;
case LINEERR_INVALPRIVSELECT:
MessageBox (hWnd, "Requested invalid priviledges", "", MB_OK);
break;
case LINEERR_INVALMEDIAMODE:
MessageBox (hWnd, "Requested invalid media mode", "", MB_OK);
break;
case LINEERR_LINEMAPPERFAILED:
MessageBox (hWnd, "Line mapper failed", "", MB_OK);
break;
case LINEERR_INVALPOINTER:
MessageBox (hWnd, "The specified pointer parameter is invalid.",
"", MB_OK);
break;
case LINEERR_OPERATIONFAILED:
MessageBox (hWnd, "Operation failed.", "", MB_OK);
break;
case LINEERR_INVALLINEHANDLE:
MessageBox (hWnd, "Invalid line handle", "", MB_OK);
break;
case LINEERR_INVALCALLHANDLE:
MessageBox (hWnd, "Invalid call handle", "", MB_OK);
break;
case LINEERR_INVALCALLSELECT:
MessageBox (hWnd, "Invalid call selection", "", MB_OK);
break;
case LINEERR_NODEVICE:
MessageBox (hWnd, "No associated device for given class",
"", MB_OK);
break;
case LINEERR_OPERATIONUNAVAIL:
MessageBox (hWnd, "The operation is unavailable",
"", MB_OK);
break;
case LINEERR_INVALPARAM:
MessageBox(hWnd, "Invalid Paramater", "", MB_OK);
break;
case LINEERR_TARGETNOTFOUND:
MessageBox(hWnd, "Target Not Found", "", MB_OK);
break;
case LINEERR_NOREQUEST:
MessageBox(hWnd, "No outstanding Assisted Telephony requests.", "", MB_OK);
break;
}
}
LRESULT CALLBACK Dial ( HWND hDlg, // window handle of the dialog box
UINT message, // type of message
WPARAM wParam, // message-specific information
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG: // message: initialize dialog box
return (TRUE);
case WM_COMMAND: // message: received a command
if ( LOWORD(wParam) == IDOK ) // "OK" box selected?
{
GetDlgItemText(hDlg, IDC_NAME, szName, 128);
GetDlgItemText(hDlg, IDC_NUMBER, szNumber, 128);
// put up a dialog box to obtain a string to dial from the user
//...........................................................
strcpy(myCallInfo[0].szDialStringOriginal, szNumber);
//allocate buffer for the LINEADDRESSCAPS strucuture
//...................................................
plineTranslateOutput = (LINETRANSLATEOUTPUT *) calloc (1, sizeof(LINETRANSLATEOUTPUT)+1000);
plineTranslateOutput->dwTotalSize = sizeof(LINETRANSLATEOUTPUT) + 1000;
// translate the Address to a dialable address and Canonical address
//.....................................................................
lRet = lineTranslateAddress(myInfo.lineApp, myLineInfo[OWNER].dwLineID, myInfo.dwAPIVersion,
myCallInfo[0].szDialStringOriginal, 0, 0, plineTranslateOutput);
if (lRet == 0)
{
strncpy(myCallInfo[0].szDialString, (LPSTR)(plineTranslateOutput)
+ plineTranslateOutput->dwDialableStringOffset,
plineTranslateOutput->dwDialableStringSize);
strncpy(myCallInfo[0].szDialStringCanonical,(LPSTR)(plineTranslateOutput)
+ plineTranslateOutput->dwDisplayableStringOffset,
plineTranslateOutput->dwDisplayableStringSize);
myCallInfo[0].dwTranslateResults = plineTranslateOutput->dwTranslateResults;
}
else
{
wsprintf ( buf,"lineTranslateAddress failed, err=x%lx", lRet);
lineError(lRet);
break;
}
//lineMakeCall
//................................................................
plineCallParams = (LINECALLPARAMS *) calloc (1, sizeof(LINECALLPARAMS)+1000);
plineCallParams->dwTotalSize = sizeof(LINECALLPARAMS) + 1000;
plineCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
plineCallParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM;
plineCallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
plineCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
plineCallParams->dwAddressID = 0;
plineCallParams->dwMinRate = 1200;
plineCallParams->dwMaxRate = 2400;
lRet = lineMakeCall(myLineInfo[OWNER].hLine,&myCallInfo[0].hCall,
myCallInfo[0].szDialString ,0, plineCallParams);
if (lRet > 0)
{
wsprintf (buf, "lineMakeCall suceeded!");
SendMessage(hListWnd, LB_INSERTSTRING, (WPARAM) -1, (LONG) (LPSTR) buf) ;
myCallInfo[0].dwRequestID = lRet;
}
else
{
wsprintf ( buf,"lineMakeCall failed, err=x%lx", lRet);
lineError(lRet);
break;
}
EndDialog(hDlg, TRUE); // Exit the dialog
return (TRUE);
}
if ( LOWORD(wParam) == IDCANCEL) // "OK" box selected?
{
EndDialog(hDlg, TRUE); // Exit the dialog
return (TRUE);
}
break;
}
return (FALSE);
}
LRESULT CALLBACK About( HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);
case WM_COMMAND:
if ( LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}